//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
//

#include "Net_Inter.h"

Define_Module(Net_Inter);

//gets messages from the outside, unpacks the header and send it to the fragmentUnit
//gets messages from the fragmentUnit, repacks the header and send it to the outPhys gate
void Net_Inter::handleMessage(cMessage* msg)
{
	NetworkPacket* packet = dynamic_cast<NetworkPacket*>(msg);
	int packetSize;

	if(packet != NULL) // the packet is NetworkPacket
	{
		packetSize = packet->getByteLength();

		//checks if the message comes from the outside
		if(strcmp(packet->getArrivalGate()->getName(), "inPhys") == 0)
		{
			if (packetSize >= MIN_PACKET_SIZE && packetSize <= MAX_PACKET_SIZE)
			{
				packet->setByteLength(packetSize - HEADER_SIZE);
				send(packet->dup(), "outLogical");
			}
		}
		else //the message comes from the fragmentUnit
		{
			packet->setByteLength(packetSize + HEADER_SIZE);
			this->PrepareToSend(packet->dup());
		}
		delete packet;
	}
	else //the message is not NetworkPacket
	{
		if(msg->isSelfMessage()) //signals the line suppose to be free
		{
			if(!this->m_SendQueue.empty())
			{
				cMessage* selfMsg = new cMessage();
				if(!this->getParentModule()->gate("outChannel")->isBusy())
				{
					this->send(((cMessage*)this->m_SendQueue.pop()), "outPhys");
					this->scheduleAt(this->getParentModule()->gate("outChannel")->getTransmissionFinishTime() , selfMsg);
				}
				else
				{
					//schedule a "reminder" to send the message when the line is free
					this->scheduleAt(this->getParentModule()->gate("outChannel")->getTransmissionFinishTime() , selfMsg);
				}
			}
		}
		delete msg;
	}
}

//sets a "reminder" message to send the message when the line is free
void Net_Inter::PrepareToSend(NetworkPacket* msg)
{
	cMessage* selfMsg = new cMessage();
	if(!this->getParentModule()->gate("outChannel")->isBusy() && this->m_SendQueue.empty())
	{
		this->scheduleAt(simTime() , selfMsg);
	}
	msg->entrySizeOfQueue = this->m_SendQueue.getLength();
	this->m_SendQueue.insert(msg);
}

